﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Linq;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Newtonsoft.Json;

namespace CuteRibs.D3Armory.Models
{
	#region Hero
	/// <summary>
	/// {
	///		"id": 6875500,
	///		"name": "Valkyrie",
	///		"class": "demon-hunter",
	///		"gender": 1,
	///		"level": 60,
	///		"paragonLevel": 0,
	///		"hardcore": false,
	///		"skills": {},
	///		"items": {},
	///		"followers": {},
	///		"stats": {},
	///		"kills": {},
	///		"progress": {},
	///		"dead": false,
	///		"last-updated": 1342947987
	///	}
	/// </summary>
	[JsonObject]
	public class Hero : BNObjectBase
	{
		[JsonProperty("id")]
		public uint Id { get; set; }

		[JsonProperty("name")]
		public string Name { get; set; }

		[JsonProperty("class")]
		[JsonConverter(typeof(ClassConverter))]
		public Class Class { get; set; }

		[JsonProperty("gender")]
		public byte Gender { get; set; }

		[JsonProperty("level")]
		public ushort Level { get; set; }

		[JsonProperty("paragonLevel")]
		public ushort ParagonLevel { get; set; }

		[JsonProperty("hardcore")]
		public bool Hardcore { get; set; }

		[JsonProperty("skills")]
		public HeroSkills Skills { get; set; }

		[JsonProperty("items")]
		public HeroItems Items { get; set; }

		[JsonProperty("followers")]
		public HeroFollowers Followers { get; set; }

		[JsonProperty("stats")]
		public HeroStats Stats { get; set; }

		[JsonProperty("kills")]
		public HeroKills Kills { get; set; }

		[JsonProperty("progress")]
		public GameProgression Progress { get; set; }

		[JsonProperty("last-updated")]
		[JsonConverter(typeof(BNDateTimeConverter))]
		public DateTime LastUpdated { get; set; }

		[JsonProperty("dead")]
		public bool Dead { get; set; }

		#region HeroSkills
		/// <summary>
		/// {
		///		"active": [],
		///		"passive": []
		///	},
		/// </summary>
		[JsonObject]
		public class HeroSkills
		{
			[JsonProperty("active")]
			public SkillSet[] Active { get; set; }

			[JsonProperty("passive")]
			public SkillSet[] Passive { get; set; }
		}
		#endregion

		#region HeroItems
		/// <summary>
		/// {
		///		"head": {},
		///		"torso": {},
		///		"feet": {},
		///		"hands": {},
		///		"shoulders": {},
		///		"legs": {},
		///		"bracers": {},
		///		"mainHand": {},
		///		"offHand": {},
		///		"waist": {},
		///		"rightFinger": {},
		///		"leftFinger": {},
		///		"neck": {}
		///	}
		/// </summary>
		[JsonObject]
		public class HeroItems
		{
			private ItemBrief[] allitems;

			[JsonIgnore]
			public ItemBrief[] AllItems
			{
				get
				{
					if (this.allitems == null)
					{
						this.allitems = new ItemBrief[]
						{
							this.Head,
							this.Torso,
							this.Feet,
							this.Hands,
							this.Shoulders,
							this.Legs,
							this.Bracers,
							this.MainHand,
							this.OffHand,
							this.Waist,
							this.RightFinger,
							this.LeftFinger,
							this.Neck
						}.Where(i => i != null).ToArray();
					}

					return this.allitems;
				}
			}

			[JsonProperty("head")]
			[ItemSlot(ItemSlot.Head)]
			public ItemBrief Head { get; set; }

			[JsonProperty("torso")]
			[ItemSlot(ItemSlot.Torso)]
			public ItemBrief Torso { get; set; }

			[JsonProperty("feet")]
			[ItemSlot(ItemSlot.Feet)]
			public ItemBrief Feet { get; set; }

			[JsonProperty("hands")]
			[ItemSlot(ItemSlot.Hands)]
			public ItemBrief Hands { get; set; }

			[JsonProperty("shoulders")]
			[ItemSlot(ItemSlot.Shoulders)]
			public ItemBrief Shoulders { get; set; }

			[JsonProperty("legs")]
			[ItemSlot(ItemSlot.Legs)]
			public ItemBrief Legs { get; set; }

			[JsonProperty("bracers")]
			[ItemSlot(ItemSlot.Bracers)]
			public ItemBrief Bracers { get; set; }

			[JsonProperty("mainHand")]
			[ItemSlot(ItemSlot.MainHand)]
			public ItemBrief MainHand { get; set; }

			[JsonProperty("offHand")]
			[ItemSlot(ItemSlot.OffHand)]
			public ItemBrief OffHand { get; set; }

			[JsonProperty("waist")]
			[ItemSlot(ItemSlot.Waist)]
			public ItemBrief Waist { get; set; }

			[JsonProperty("rightFinger")]
			[ItemSlot(ItemSlot.RightFinger)]
			public ItemBrief RightFinger { get; set; }

			[JsonProperty("leftFinger")]
			[ItemSlot(ItemSlot.LeftFinger)]
			public ItemBrief LeftFinger { get; set; }

			[JsonProperty("neck")]
			[ItemSlot(ItemSlot.Neck)]
			public ItemBrief Neck { get; set; }
		}
		#endregion

		#region HeroFollowers
		/// <summary>
		///	{
		///		"templar": {},
		///		"scoundrel": {},
		///		"enchantress": {}
		///	}
		/// </summary>
		[JsonObject]
		public class HeroFollowers
		{
			[JsonProperty("templar")]
			public Follower Templar { get; set; }

			[JsonProperty("scoundrel")]
			public Follower Scoundrel { get; set; }

			[JsonProperty("enchantress")]
			public Follower Enchantress { get; set; }
		}
		#endregion

		#region HeroStats
		/// <summary>
		/// {
		///		"life": 33335,
		///		"damage": 24694.6,
		///		"attackSpeed": 1.4839999747276307,
		///		"armor": 2505,
		///		"strength": 331,
		///		"dexterity": 1437,
		///		"vitality": 874,
		///		"intelligence": 426,
		///		"physicalResist": 71,
		///		"fireResist": 76,
		///		"coldResist": 114,
		///		"lightningResist": 37,
		///		"poisonResist": 114,
		///		"arcaneResist": 37,
		///		"critDamage" : 2.0,
		///		"damageIncrease": 14.369999885559082,
		///		"critChance": 0.07999999821186066,
		///		"damageReduction": 0.45504099130630493,
		///		"blockChance" : 0.0,
		///		"thorns" : 199.0,
		///		"lifeSteal" : 0.0,
		///		"lifePerKill" : 0.0,
		///		"goldFind" : 0.30000000000000004,
		///		"magicFind" : 1.2400000000000002,
		///		"blockAmountMin" : 0,
		///		"blockAmountMax" : 0,
		///		"lifeOnHit" : 362.0,
		///		"primaryResource" : 133,
		///		"secondaryResource" : 0
		///	}
		/// </summary>
		[JsonObject]
		public class HeroStats
		{
			[JsonProperty("life")]
			public uint Life { get; set; }

			[JsonProperty("damage")]
			public uint Damage { get; set; }

			[JsonProperty("attackSpeed")]
			public double AttackSpeed { get; set; }

			[JsonProperty("armor")]
			public uint Armor { get; set; }

			[JsonProperty("strength")]
			public uint Strength { get; set; }

			[JsonProperty("dexterity")]
			public uint Dexterity { get; set; }

			[JsonProperty("vitality")]
			public uint Vitality { get; set; }

			[JsonProperty("intelligence")]
			public uint Intelligence { get; set; }

			[JsonProperty("physicalResist")]
			public uint PhysicalResist { get; set; }

			[JsonProperty("fireResist")]
			public uint FireResist { get; set; }

			[JsonProperty("coldResist")]
			public uint ColdResist { get; set; }

			[JsonProperty("lightningResist")]
			public uint LightningResist { get; set; }

			[JsonProperty("poisonResist")]
			public uint PoisonResist { get; set; }

			[JsonProperty("arcaneResist")]
			public uint ArcaneResist { get; set; }

			[JsonProperty("critDamage")]
			public double CritDamage { get; set; }

			[JsonProperty("damageIncrease")]
			public double DamageIncrease { get; set; }

			[JsonProperty("critChance")]
			public double CritChance { get; set; }

			[JsonProperty("damageReduction")]
			public double DamageReduction { get; set; }

			[JsonProperty("blockChance")]
			public double BlockChance { get; set; }

			[JsonProperty("thorns")]
			public double Thorns { get; set; }

			[JsonProperty("lifeSteal")]
			public double LifeSteal { get; set; }

			[JsonProperty("lifePerKill")]
			public double LifePerKill { get; set; }

			[JsonProperty("goldFind")]
			public double GoldFind { get; set; }

			[JsonProperty("magicFind")]
			public double MagicFind { get; set; }

			[JsonProperty("blockAmountMin")]
			public ushort BlockAmountMin { get; set; }

			[JsonProperty("blockAmountMax")]
			public ushort BlockAmountMax { get; set; }

			[JsonProperty("lifeOnHit")]
			public double LifeOnHit { get; set; }

			[JsonProperty("primaryResource")]
			public ushort PrimaryResource { get; set; }

			[JsonProperty("secondaryResource")]
			public ushort SecondaryResource { get; set; }
		}
		#endregion

		#region HeroKills
		/// <summary>
		/// {
		///		"elites": 4019,
		///	}
		/// </summary>
		[JsonObject]
		public class HeroKills
		{
			[JsonProperty("elites")]
			public float Elites { get; set; }
		}
		#endregion
	} 
	#endregion

	#region Follower
	/// <summary>
	///	{
	///		"slug": "templar",
	///		"level": 60,
	///		"items": {},
	///		"stats": {},
	///		"skills": []
	///	},
	/// </summary>
	[JsonObject]
	public class Follower
	{
		[JsonProperty("slug")]
		public string Slug { get; set; }

		[JsonProperty("level")]
		public byte Level { get; set; }

		[JsonProperty("items")]
		public FollowerItems Items { get; set; }

		[JsonProperty("stats")]
		public FollowerStats Stats { get; set; }

		[JsonProperty("skills")]
		public SkillSet[] Skills { get; set; }

		#region FollowerItems
		/// <summary>
		/// {
		///		"special": {},
		///		"mainHand": {},
		///		"offHand": {},
		///		"rightFinger": {},
		///		"leftFinger": {},
		///		"neck": {}
		///	}
		/// </summary>
		[JsonObject]
		public class FollowerItems
		{
			private ItemBrief[] allitems;

			[JsonIgnore]
			public ItemBrief[] AllItems
			{
				get
				{
					if (this.allitems == null)
					{
						this.allitems = new ItemBrief[]
						{
							this.Special,
							this.MainHand,
							this.OffHand,
							this.RightFinger,
							this.LeftFinger,
							this.Neck
						}.Where(i => i != null).ToArray();
					}

					return this.allitems;
				}
			}

			[JsonProperty("special")]
			[ItemSlot(ItemSlot.Special)]
			public ItemBrief Special { get; set; }

			[JsonProperty("mainHand")]
			[ItemSlot(ItemSlot.MainHand)]
			public ItemBrief MainHand { get; set; }

			[JsonProperty("offHand")]
			[ItemSlot(ItemSlot.OffHand)]
			public ItemBrief OffHand { get; set; }

			[JsonProperty("rightFinger")]
			[ItemSlot(ItemSlot.RightFinger)]
			public ItemBrief RightFinger { get; set; }

			[JsonProperty("leftFinger")]
			[ItemSlot(ItemSlot.LeftFinger)]
			public ItemBrief LeftFinger { get; set; }

			[JsonProperty("neck")]
			[ItemSlot(ItemSlot.Neck)]
			public ItemBrief Neck { get; set; }
		}
		#endregion

		#region FollowerStats
		/// <summary>
		/// {
		///		"goldFind": 3,
		///		"magicFind": 0,
		///		"experienceBonus": 0
		///	}
		/// </summary>
		[JsonObject]
		public class FollowerStats
		{
			[JsonProperty("goldFind")]
			public uint GoldFind { get; set; }

			[JsonProperty("magicFind")]
			public uint MagicFind { get; set; }

			[JsonProperty("experienceBonus")]
			public uint ExperienceBonus { get; set; }
		}
		#endregion
	}
	#endregion

	#region ItemBrief
	/// <summary>
	/// {
	///		"id": "Amulet11",
	///		"name": "Troll's Omen",
	///		"icon": "amulet11_demonhunter_male",
	///		"displayColor": "yellow",
	///		"tooltipParams": "item/CjwIwKODtQcSBwgEFVLqvlsdyNLzZR2e1VN0HaCBE64drC4wTCILCAEVikIDABgmIBYwCTjfA0AAUAxg4AMYpKn3uwtQAFgC"
	///	}
	/// </summary>
	[JsonObject]
	public class ItemBrief
	{
		public ItemSlot ItemSlot { get; set; }

		[JsonProperty("id")]
		public string Id { get; set; }

		[JsonProperty("name")]
		public string Name { get; set; }

		[JsonProperty("icon")]
		public string Icon { get; set; }

		[JsonProperty("displayColor")]
		public string DisplayColor { get; set; }

		[JsonProperty("tooltipParams")]
		public string TooltipParams { get; set; }
	}
	#endregion

	#region SkillSet
	/// <summary>
	/// {
	///		"skill": {}
	///		"rune": {}
	///	}
	/// </summary>
	[JsonObject]
	public class SkillSet
	{
		[JsonProperty("skill")]
		public Skill Skill { get; set; }

		[JsonProperty("rune")]
		public Rune Rune { get; set; }
	} 
	#endregion

	#region Skill
	/// <summary>
	/// {
	///		"slug": "hungering-arrow",
	///		"name": "Hungering Arrow",
	///		"icon": "demonhunter_hungeringarrow",
	///		"level": 1,
	///		"tooltipUrl": "skillSet/demon-hunter/hungering-arrow",
	///		"description": "Generate: 3  ///a  35% chance to pierce through targets.",
	///		"simpleDescription": "Heals you or the Templar.",
	///		"skillCalcId": "a"
	///	}
	/// </summary>
	[JsonObject]
	public class Skill
	{
		[JsonProperty("slug")]
		public string Slug { get; set; }

		[JsonProperty("name")]
		public string Name { get; set; }

		[JsonProperty("icon")]
		public string Icon { get; set; }

		[JsonProperty("level")]
		public byte Level { get; set; }

		[JsonProperty("tooltipUrl")]
		public string TooltipUrl { get; set; }

		[JsonProperty("description")]
		public string Description { get; set; }

		[JsonProperty("simpleDescription")]
		public string SimpleDescription { get; set; }

		[JsonProperty("skillCalcId")]
		public string SkillCalcId { get; set; }
	}
	#endregion

	#region ActiveSkill
	/// <summary>
	/// {
	///		"slug": "hungering-arrow",
	///		"name": "Hungering Arrow",
	///		"icon": "demonhunter_hungeringarrow",
	///		"level": 1,
	///		"categorySlug": "primary",
	///		"tooltipUrl": "skillSet/demon-hunter/hungering-arrow",
	///		"description": "Generate: 3 Hatred\r\n\r\nFire a magically imbued arrow that seeks out targets for 115% weapon damage and has		    ///a  35% chance to pierce through targets.",
	///		"simpleDescription": "Generate: 3 Hatred\r\n\r\nFire a piercing arrow that seeks additional targets.",
	///		"skillCalcId": "a"
	///	},
	/// </summary>
	[JsonObject]
	public class ActiveSkill : Skill
	{
		[JsonProperty("categorySlug")]
		public string CategorySlug { get; set; }
	}
	#endregion

	#region PassiveSkill
	/// <summary>
	/// {
	///		"slug": "steady-aim",
	///		"name": "Steady Aim",
	///		"icon": "demonhunter_passive_steadyaim",
	///		"tooltipUrl": "skillSet/demon-hunter/steady-aim",
	///		"description": "As long as there are no enemies within 10 yards, all damage is increased by 20%.",
	///		"flavor": "\"Flee if you can, demon. I have a quiver full of friends who fly faster than you.\" —Tyla Shrikewing",
	///		"skillCalcId": "Y",
	///		"level": 16
	///	}
	/// </summary>
	[JsonObject]
	public class PassiveSkill : Skill
	{
		[JsonProperty("flavor")]
		public string Flavor { get; set; }
	}
	#endregion

	#region Rune
	/// <summary>
	/// {
	///		"slug": "spike-trap-d",
	///		"type": "d",
	///		"name": "Scatter",
	///		"level": 55,
	///		"description": "Simultaneously place all 3 traps.",
	///		"simpleDescription": "Simultaneously place multiple traps.",
	///		"tooltipParams": "rune/spike-trap/d",
	///		"skillCalcId": "c",
	///		"order": 4
	///	}
	/// </summary>
	[JsonObject]
	public class Rune
	{
		[JsonProperty("slug")]
		public string Slug { get; set; }

		[JsonProperty("type")]
		public string Type { get; set; }

		[JsonProperty("name")]
		public string Name { get; set; }

		[JsonProperty("level")]
		public byte Level { get; set; }

		[JsonProperty("description")]
		public string Description { get; set; }

		[JsonProperty("simpleDescription")]
		public string SimpleDescription { get; set; }

		[JsonProperty("tooltipParams")]
		public string TooltipParams { get; set; }

		[JsonProperty("skillCalcId")]
		public string SkillCalcId { get; set; }

		[JsonProperty("order")]
		public byte Order { get; set; }
	}
	#endregion
}
